package ControllerLayer.ControlManager;

import PresentationLayout.Control.IPresentation;
import PresentationLayout.Control.Presentation;

import DataLayer.DataManager.IDataManager;
import ControllerLayer.ControlServices.Preprocessor.IPreprocessor;
import ControllerLayer.ControlServices.Normalizer.INormalizer;
import ControllerLayer.ControlServices.Normalizer.MainNormalizer;
import ControllerLayer.ControlServices.Preprocessor.MainPreprocessor;
import ControllerLayer.ControlServices.Recognizer.IRecognizer;
import ControllerLayer.ControlServices.Recognizer.MainRecognizer;
import ControllerLayer.ControlServices.Segmenter.ISegmenter;
import ControllerLayer.ControlServices.Segmenter.MainSegmenter;
import ControllerLayer.ControlServices.Teacher.ITeacher;
import ControllerLayer.ControlServices.Teacher.MainTeacher;
import DataLayer.DataManager.DataManager;
import java.awt.geom.Line2D;

import java.io.IOException;
import java.util.ArrayList;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
import javax.xml.parsers.ParserConfigurationException;



/**
 * The Main Control class
 * @author Kovács Áron
 */
public class MainControl implements IControlManager {

    protected IDataManager dataManager;
    protected IPreprocessor preprocessor;
    protected ISegmenter segmenter;
    protected INormalizer normalizer;
    protected IRecognizer recognizer;
    protected ITeacher teacher;
    protected IPresentation presentation;

    /**
     * The constructor
     * @throws IOException
     * @throws ParserConfigurationException
     */
    public MainControl() throws IOException, ParserConfigurationException {
        dataManager = new DataManager();
        preprocessor = new MainPreprocessor();
        segmenter = new MainSegmenter();
        normalizer = new MainNormalizer();
        recognizer = new MainRecognizer();
        teacher = new MainTeacher();
        presentation = new Presentation(this);
    }

    /**
     * Recognizes the text on the loaded image after preprocessing and segmentating it.
     */
    public void recognizeText() {
        preprocessor.preprocessOriginalImage(dataManager.getImageInfo());
        presentation.setPreprocessedImage(dataManager.getImageInfo());
        ////System.out.println("image preprocessed");
        segmenter.segmentLines(dataManager.getImageComponentsInfo(), dataManager.getImageInfo());
        ////System.out.println("segmentate lines");
        segmenter.segmentWords(dataManager.getImageComponentsInfo(), dataManager.getImageInfo());
        ////System.out.println("segmentate words");
        segmenter.segmentCharacters(dataManager.getImageComponentsInfo(), dataManager.getImageInfo());
        ////System.out.println("segmentate chars");
        recognizer.recognizeText(dataManager.getCharacterStatistics(), dataManager.getImageComponentsInfo(), dataManager.getImageInfo(), dataManager.getKnowledgeBaseControl().getKnowledgeBase(), normalizer);
        ////System.out.println("output text");
        //System.out.println(dataManager.getImageComponentsInfo().getRetreivedText());
    }

    /**
     * Segmentates the preprocessed loaded image, and finds the words on it.
     * @return The coordinates of the words on the image.
     */
    public ArrayList<Line2D> generateWords() {
        preprocessor.preprocessOriginalImage(dataManager.getImageInfo());
        presentation.setPreprocessedImage(dataManager.getImageInfo());
        ////System.out.println("image preprocessed");
        segmenter.segmentLines(dataManager.getImageComponentsInfo(), dataManager.getImageInfo());
        ////System.out.println("segmentate lines");
        segmenter.segmentWords(dataManager.getImageComponentsInfo(), dataManager.getImageInfo());
        ////System.out.println("segmentate words");
        return dataManager.getImageComponentsInfo().getWords();
    }

    /**
     *
     * @return The Data Manager.
     */
    public IDataManager getDataManager() {
        return dataManager;
    }

    /**
     * Inserts the coordinates of the characters from the actual word int the Image Components Info.
     * @param word - The actual word.
     * @param wordID - The number of the actual word.
     * @param charCoords - The coordinates of the characters in the actual word.
     */
    public void insertWordInformationInImageComponents(String word, int wordID, ArrayList<Integer> charCoords) {
        ////System.out.println("mainCtr: Adding new characters");
        dataManager.getImageComponentsInfo().insertWordInformationInImageComponents(word, wordID, charCoords);
    }

    /**
     * Delegates the character normalization.
     */
    public void sendConfirmationForNormalization() {
        normalizer.normalizeCharacters(dataManager.getImageComponentsInfo(), dataManager.getImageInfo(), dataManager.getKnowledgeBaseControl());
    }

    /**
     * Exports the information in the knowledgebase.
     * @return
     */
    public boolean exportDatabase(String exportPath)
    {
        if (dataManager.getKnowledgeBaseControl().exportKnowledgeBase(exportPath)) {
            dataManager.getKnowledgeBaseControl().transformKnowledgeBase();
            return true;
        } else {
            return false;
        }

    }

    /**
     * Imports another knowledgebase and merges it with the existing one.
     * @param kbPath - The path to the knowledgebase.
     */
    public void importAndMergeDatabase(String kbPath) {
        dataManager.getKnowledgeBaseControl().loadAndMergeKnowledgeBase(kbPath);
    }

    /**
     * Generates a PDF document from the recognized text.
     * @param text - The text to be written in the PDF.
     * @param nameOfPDF - The path and name of the desired PDF document.
     */
    public void generatePDF(String text, String nameOfPDF) {
        dataManager.getRetrievedTextComponent().setRetrievedText(text);
        dataManager.getRetrievedTextComponent().generatePDF(nameOfPDF);
    }

    /**
     * Sets the Look And Feel of the application.
     */
    public static void setLAF() {
        try {
            UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
        } catch (UnsupportedLookAndFeelException e) {
            System.out.println("UnsupportedLookAndFeelException");
        } catch (ClassNotFoundException e) {
            System.out.println("ClassNotFoundException");
        } catch (InstantiationException e) {
            System.out.println("InstantiationException");
        } catch (IllegalAccessException e) {
            System.out.println("IllegalAccessException");
        }
    }

    /**
     * Main function, initializes the components.
     * @param args
     */
    public static void main(String args[]) {
        java.awt.EventQueue.invokeLater(new Runnable() {

            public void run() {
                try {
                    try {
                        setLAF();
                        MainControl mainCtrl = new MainControl();
                    } catch (ParserConfigurationException ex) {
                        System.out.println("ParserConfigurationException" + ex);
                    }
                } catch (IOException ex) {
                    System.out.println("maincontrol init fail");
                }

            }
        });
    }
}
